package cc.rengu.oltp.service.realize.impl;

import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.ChannelCallCfgMapper;
import cc.rengu.oltp.service.common.dao.SrcTxnAuthCfgMapper;
import cc.rengu.oltp.service.common.dao.SrcTxnExcpCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.ChannelCallCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SrcTxnAuthCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SrcTxnExcpCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.SrcTxnAuthCfg;
import cc.rengu.oltp.service.common.entity.SrcTxnExcpCfg;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizHeader;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.TxnInfoService;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 交易配置信息服务实现类
 * Created by wangcheng on 2021/12/2 16:43
 */
public class TxnInfoServiceImpl implements TxnInfoService {
    RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    @Override
    public TxnInfo getCurrentTxnInfo() throws Exception {
        BizHeader bizHeader = getBizHeaderInfo();
        if (null == bizHeader.getInstId() || bizHeader.getInstId().isEmpty() || null == bizHeader.getSrcSysId() ||
                bizHeader.getSrcSysId().isEmpty() || null == bizHeader.getTxnNum() || bizHeader.getTxnNum().isEmpty()) {
            rglog.error("业务参数异常,instId:<{}>,msgSrcId:<{}>,txnNum:<{}>,bizType:<{}>", bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizHeader.getBizType());
            throw new BizException(OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL.getRespCode(), OltpRpcdEnum.PARAM_IS_EMPTY_OR_NULL.getRespDesc());
        }
        String bizType = (null == bizHeader.getBizType() || bizHeader.getBizType().isEmpty()) ? "00" : bizHeader.getBizType().trim();
        String channelId = (null == bizHeader.getChanlId() || bizHeader.getChanlId().isEmpty()) ? "*" : bizHeader.getChanlId().trim();
        String txnKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + channelId.trim() + bizHeader.getTxnNum().trim() + bizType.trim();
        /* 获取交易路由配置信息 */
        TxnInfo txnInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.TXN_INFO_CACHE, txnKey), TxnInfo.class);
        if (null == txnInfo) {
            rglog.info("未单独配置交易渠道<{}-{}>的交易配置，使用渠道通用交易配置!", bizHeader.getSrcSysId(), bizHeader.getChanlId());
            txnKey = bizHeader.getInstId().trim() + bizHeader.getSrcSysId().trim() + "*" + bizHeader.getTxnNum().trim() + bizType.trim();
            txnInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.TXN_INFO_CACHE, txnKey), TxnInfo.class);
        }
        if (null == txnInfo) {
            rglog.debug("从数据库查询交易信息");
            /* 获取渠道交易权限配置信息 */
            SrcTxnAuthCfgMapper srcTxnAuthCfgMapper = new SrcTxnAuthCfgMapperImpl();
            SrcTxnAuthCfg srcTxnAuthCfg = srcTxnAuthCfgMapper.selectSrcTxnAuthCfgByPrimaryKey(bizHeader.getInstId().trim(), bizHeader.getSrcSysId().trim(), channelId, bizHeader.getTxnNum().trim(), bizType);
            if (null == srcTxnAuthCfg) {
                rglog.info("未获取到srcTxnAuthCfg，chanlId = <{}>", channelId);
                srcTxnAuthCfg = srcTxnAuthCfgMapper.selectSrcTxnAuthCfgByPrimaryKey(bizHeader.getInstId().trim(), bizHeader.getSrcSysId().trim(), "*", bizHeader.getTxnNum().trim(), bizType);
                if (null == srcTxnAuthCfg) {
                    rglog.error("instId:<{}>,msgSrcId:<{}>,transChannelId:<{}>,txnNum:<{}>,bizType:<{}> is not support.", bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getChanlId(), bizHeader.getTxnNum(), bizType);
                    throw new BizException(OltpRpcdEnum.TRANS_NOT_SUPPORT);
                } else {
                    rglog.debug("srcTxnAuthCfg = <{}>，chanlId = *", JSONObject.toJSONString(srcTxnAuthCfg));
                }
            } else {
                rglog.debug("srcTxnAuthCfg = <{}>，chanlId =<{}>", JSONObject.toJSONString(srcTxnAuthCfg), channelId);
            }
            txnInfo = new TxnInfo();
            txnInfo.setTxnKey(txnKey);
            txnInfo.setSrcTxnAuthCfg(srcTxnAuthCfg);
            /* 获取交易异常配置信息 */
            SrcTxnExcpCfgMapper srcTxnExcpCfgMapper = new SrcTxnExcpCfgMapperImpl();
            SrcTxnExcpCfg srcTxnExcpCfg = srcTxnExcpCfgMapper.selectSrcTxnExcpCfgByPrimaryKey(bizHeader.getInstId(), bizHeader.getSrcSysId(), bizHeader.getTxnNum(), bizType);
            if (null != srcTxnExcpCfg) {
                txnInfo.setSrcTxnExcpCfg(srcTxnExcpCfg);
            }
            /* 获取交易码通道调用配置关系 */
            ChannelCallCfgMapper channelCallCfgMapper = new ChannelCallCfgMapperImpl();
            List<ChannelCallCfg> channelCallCfgList = channelCallCfgMapper.selectChannelCallCfgByTxnNum(srcTxnAuthCfg.getInstId(), srcTxnAuthCfg.getMsgSrcId(), srcTxnAuthCfg.getTransChannelId(), srcTxnAuthCfg.getTxnNum(), srcTxnAuthCfg.getBizType());
            if (null == channelCallCfgList || channelCallCfgList.isEmpty()) {
                channelCallCfgList = channelCallCfgMapper.selectChannelCallCfgByTxnNum(srcTxnAuthCfg.getInstId(), srcTxnAuthCfg.getMsgSrcId(), "*", srcTxnAuthCfg.getTxnNum(), srcTxnAuthCfg.getBizType());
            }
            if (null != channelCallCfgList && !channelCallCfgList.isEmpty()) {
                channelCallCfgList = channelCallCfgList.stream().sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
                txnInfo.setChannelCallCfgList(channelCallCfgList);
            }
        }
        return txnInfo;
    }

    @Override
    public TxnInfo getTxnInfo(String instId, String msgSrcId, String transChannelId, String txnNum, String bizType) throws Exception {
        bizType = StringUtil.isEmptyOrNull(bizType) ? "00" : bizType;
        String txnKey = instId + msgSrcId + transChannelId + txnNum + bizType;
        TxnInfo txnInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.TXN_INFO_CACHE, txnKey), TxnInfo.class);
        if (null == txnInfo) {
            rglog.info("未单独配置交易渠道<{}-{}>的交易配置，使用渠道通用交易配置!", msgSrcId, transChannelId);
            txnKey = instId + msgSrcId + "*" + txnNum + bizType;
            txnInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.TXN_INFO_CACHE, txnKey), TxnInfo.class);
        }
        if (null == txnInfo) {
            rglog.debug("从数据库查询交易信息");
            /* 获取渠道交易权限配置信息 */
            SrcTxnAuthCfgMapper srcTxnAuthCfgMapper = new SrcTxnAuthCfgMapperImpl();
            SrcTxnAuthCfg srcTxnAuthCfg = srcTxnAuthCfgMapper.selectSrcTxnAuthCfgByPrimaryKey(instId, msgSrcId, transChannelId, txnNum, bizType);
            if (null == srcTxnAuthCfg) {
                srcTxnAuthCfg = srcTxnAuthCfgMapper.selectSrcTxnAuthCfgByPrimaryKey(instId, msgSrcId, "*", txnNum, bizType);
                if (null == srcTxnAuthCfg) {
                    rglog.warn("instId:<{}>,msgSrcId:<{}>,transChannelId:<{}>,txnNum:<{}>,bizType:<{}> is not support.", instId, msgSrcId, transChannelId, txnNum, bizType);
                    throw new BizException(OltpRpcdEnum.TRANS_NOT_SUPPORT);
                }
            }
            txnInfo = new TxnInfo();
            txnInfo.setTxnKey(txnKey);
            txnInfo.setSrcTxnAuthCfg(srcTxnAuthCfg);
            /* 获取交易码通道调用配置关系 */
            ChannelCallCfgMapper channelCallCfgMapper = new ChannelCallCfgMapperImpl();
            List<ChannelCallCfg> channelCallCfgList = channelCallCfgMapper.selectChannelCallCfgByTxnNum(srcTxnAuthCfg.getInstId(), srcTxnAuthCfg.getMsgSrcId(), srcTxnAuthCfg.getTransChannelId(), srcTxnAuthCfg.getTxnNum(), srcTxnAuthCfg.getBizType());
            if (null == channelCallCfgList || channelCallCfgList.isEmpty()) {
                channelCallCfgList = channelCallCfgMapper.selectChannelCallCfgByTxnNum(srcTxnAuthCfg.getInstId(), srcTxnAuthCfg.getMsgSrcId(), "*", srcTxnAuthCfg.getTxnNum(), srcTxnAuthCfg.getBizType());
            }
            if (null != channelCallCfgList && !channelCallCfgList.isEmpty()) {
                channelCallCfgList = channelCallCfgList.stream().sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
                txnInfo.setChannelCallCfgList(channelCallCfgList);
            }
        }
        return txnInfo;
    }

    /**
     * 获取业务报文头信息
     *
     * @return 业务报文头
     * @throws Exception 异常
     */
    private BizHeader getBizHeaderInfo() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        BizHeader bizHeader = new BizHeader();
        ConvertUtil.convertOutput(bizHeader);
        if (null == bizHeader.getVersion() || bizHeader.getVersion().isEmpty()) {
            bizHeader.setVersion(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.VERSION));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_VERSION, bizHeader.getVersion());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.VERSION, bizHeader.getVersion());
        }
        if (null == bizHeader.getTransDate() || bizHeader.getTransDate().isEmpty()) {
            bizHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TRANS_DATE, bizHeader.getTransDate());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TRANS_DATE, bizHeader.getTransDate());
        }
        if (null == bizHeader.getTransTime() || bizHeader.getTransTime().isEmpty()) {
            bizHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TRANS_TIME, bizHeader.getTransTime());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TRANS_TIME, bizHeader.getTransTime());
        }
        if (null == bizHeader.getTxnNum() || bizHeader.getTxnNum().isEmpty()) {
            bizHeader.setTxnNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, bizHeader.getTxnNum());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, bizHeader.getTxnNum());
        }
        if (null == bizHeader.getBizType() || bizHeader.getBizType().isEmpty()) {
            bizHeader.setBizType(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, bizHeader.getBizType());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, bizHeader.getBizType());
        }
        if (null == bizHeader.getInstId() || bizHeader.getInstId().isEmpty()) {
            bizHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_INST_ID, bizHeader.getInstId());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.INST_ID, bizHeader.getInstId());
        }
        if (null == bizHeader.getSrcSysId() || bizHeader.getSrcSysId().isEmpty()) {
            bizHeader.setSrcSysId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_SRC_SYS_ID, bizHeader.getSrcSysId());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.MSG_SRC_ID, bizHeader.getSrcSysId());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID, bizHeader.getSrcSysId());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.MSG_SRC_ID, bizHeader.getSrcSysId());
        }
        if (null == bizHeader.getChanlId() || bizHeader.getChanlId().isEmpty()) {
            bizHeader.setChanlId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_CHANNEL_ID, bizHeader.getChanlId());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TRANS_CHANNEL_ID, bizHeader.getChanlId());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID, bizHeader.getChanlId());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TRANS_CHANNEL_ID, bizHeader.getChanlId());
        }
        if (null == bizHeader.getTraceNo() || bizHeader.getTraceNo().isEmpty()) {
            bizHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRACE_NO));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TRACE_NO, bizHeader.getTraceNo());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.FRONT_SEQ_NUM, bizHeader.getTraceNo());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TRACE_NO, bizHeader.getTraceNo());
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.FRONT_SEQ_NUM, bizHeader.getTraceNo());
        }
        if (null == bizHeader.getSession() || bizHeader.getSession().isEmpty()) {
            bizHeader.setSession(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SESSION));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_SESSION, bizHeader.getSession());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SESSION, bizHeader.getSession());
        }
        if (null == bizHeader.getSignature() || bizHeader.getSignature().isEmpty()) {
            bizHeader.setSignature(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SIGNATURE));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_SIGNATURE, bizHeader.getSignature());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SIGNATURE, bizHeader.getSignature());
        }
        if (null == bizHeader.getRemark() || bizHeader.getRemark().isEmpty()) {
            bizHeader.setRemark(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.REMARK));
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_REMARK, bizHeader.getRemark());
        } else {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.REMARK, bizHeader.getRemark());
        }
        return bizHeader;
    }
}
